最短路径问题—Dijkstra算法及其实现

这里写图片描述

这里写图片描述

shortPath数组和DistantanceParent类。
最短路径算法的关键数据结构是一个数组,它保持了从原点到其他顶点(终点的最短路径)。在算法的执行过程中这个距离是变化的,直到最后,它存储了从原点开始真正的最短距离,在程序中,这个数组叫做shortPath[]. 也就是最短路径

不仅应该记录从原点到终点的最短路径,还应该记录走过的路径。幸运的是,不必要明确记录整个路径,只需要记录终点的父节点。父节点就是达到终点前的节点。有几种方法保存父节点顶点的信息,本程序选用了把父节点和距离放在一起的方法,并把结果的对象放在shortPath[]数组中。这个对象类叫做DistanceParent (距离-父节点)。



class DistanceParent  //distance  and  parent
{
    public  int  distance ;//distance  from  start  to this  vertex
    public  int parentVert; // current  parent  of  this  vertex

    //.............................
    public  DistanceParent(int pv, int d)
    {
        distance = d;
        parentVert = pv;
    }

}

//.............................................
class Vertex
{
    public  char  label; //  label,like 'A'
    public  boolean  isInTree;
    //...............................

    public  Vertex(char  lab)
    {
        label = lab;
        isInTree = false;
    }
}

//.....................................
class Graph
{
    private  final  int  MAX_VERTS = 20;
    private  final  int INFINITY = 10000000; //用一个很大的数代表无穷大
    private Vertex vertexList[] ; //list  of  vertices
    private  int  adjMat[][] ; // 邻接矩阵
    private  int  nVerts;  //当前节点数
    private  int  nTree ; //number  of  verts  in  tree
    private  DistanceParent   shortPath[] ;  //保存最短路径的数组
    private  int  currentVert ; //当前顶点
    private  int  startToCurrent ;//到当前顶点的距离

    //.......................................................

    public  Graph()
    {
        vertexList  = new  Vertex[MAX_VERTS];
        adjMat = new int[MAX_VERTS][MAX_VERTS];
        nVerts = 0;
        nTree = 0;
        for(int j = 0;j<MAX_VERTS;j++)
            for(int k=0;k<MAX_VERTS;k++)
                adjMat[j][k] = INFINITY;
        shortPath = new DistanceParent[MAX_VERTS];

    }
    //.............................................

    public void addVertex(char  lab)
    {
        vertexList[nVerts++] = new Vertex(lab);
    }

    //......................................
    public  void addEdge(int  start,int  end,int  weight)
    {
        adjMat[start][end]  = weight;
    }

    //.........................
    public  void  path()
    {
        int  startTree = 0;  //从第0格节点开始
        vertexList[startTree].isInTree = true;  //  put int tree
        nTree = 1;

        for(int  j = 0;j<nVerts;j++)
        {
            int  tempDistance = adjMat[startTree][j];
            shortPath[j] = new DistanceParent(startTree, tempDistance);
            //until all vertices  are  in  the  tree
        }
        /*
         * 1.选择shortPath[] 数组中的最小距离
         * 2.把对于的顶点放入树中,这个点变成当前顶点 ,currentVert
         * 3.根据currentVert的变化,更新所有的shortPath[]数组内容
         */

        while(nTree <nVerts)
        {
            int indexMin  = getMin();//从shortPath【】数组中获得最短路径
            int  minDintance = shortPath[indexMin].distance;

            if(minDintance == INFINITY)
            {
                System.out.println("节点不可到达");
                break;
            }
            else
            {  // reset  currentVert
                currentVert = indexMin;   //to  closest  vert
                startToCurrent =shortPath[indexMin].distance;

            }
            //put current  vertex  in  tree
            vertexList[currentVert].isInTree= true;
            nTree++;
            adjust_shortPath();  //更新最短路径数组
        }
        displayPaths(); //显示最短路径数组内容

            nTree = 0; //  clear  tree
            for (int i = 0; i < nVerts; i++)
            vertexList[i].isInTree = false;
    }

    //........................................
    public  int  getMin()
    {
        int minDistance = INFINITY;
        int  indexMin = 0;
        for(int j = 1;j<nVerts;j++)
        {
            if(!vertexList[j].isInTree &&shortPath[j].distance <minDistance)
            {
                minDistance = shortPath[j].distance;
                indexMin = j;
            }
        }
        return indexMin;
    }

    /*
     * adjust_shortPath()方法更新shortPath[]数组
     * 当程序被调用时,currentVert刚被放入树中,
     * startToCurrent时shortPath[]数组的当前项。adjust_shortPath()方法检查shortPath[]
     * 中的每一项,它使用循环计数器column依次指向每个顶点。
     * 对于shortPath[]数组的每一个项,如果对应顶点不在树中,它做三件事:
     * 1.把到当前顶点的距离(存在startToCurrent变量中)加到从currentVert顶点到column顶点的距离上
     * 结果叫做startToFringe
     * 2.把startToFringe与shortPath[]数组的当前项进行比较
     * 3.如果startToFringe更小,就替换当前项
     * 
     * 这就是Dijkstra算法的核心,它让shortPath[]数组总是存储从原点到所有已知顶点的最短路径。
     */
    public  void  adjust_shortPath()
    {
        // adjust  values  in  shortest-path  array  shortPath
        int colunm = 1; //skip  starting  vertex
        while(colunm < nVerts)
        {
            //if  this  column vertex  already  in tree  skip  it
            if(vertexList[colunm].isInTree)
            {
                colunm++;
                continue;
            }
            //calculate   distance  for  one shortPath  entry
            //get  edge  from  currentVert  to  column
            int currentToFringe = adjMat[currentVert][colunm];
            //add  distance  from  start
            int  startToFringe =startToCurrent +currentToFringe;
            //get  distance  of current  shortPath  entry
            int shortPathDistance = shortPath[colunm].distance;

            //compare  distance  from  start  with  shortPath  entry
            if(startToFringe  <shortPathDistance)  //update 
            {
                shortPath[colunm].parentVert = currentVert;
                shortPath[colunm].distance = startToFringe;
            }
            colunm++;
        }
    }

    //..........................
    public  void  displayPaths()
    {
        for(int j = 0;j<nVerts;j++)
        {
            System.out.print(vertexList[j].label + "=");
            if(shortPath[j].distance == INFINITY)
                System.out.print("inf");
            else
                System.out.print(shortPath[j].distance);
            char  parent = vertexList[shortPath[j].parentVert].label;
            System.out.print(" ("+parent +") ");
        }
        System.out.println(" ");
    }
}


////////////////////////////////////////////
class  PathApp
{
    public static void main(String[] args)
    {
        Graph   theGraph = new Graph();

        theGraph.addVertex('A'); //0
        theGraph.addVertex('B'); //1
        theGraph.addVertex('C'); //2
        theGraph.addVertex('D');  //3
        theGraph.addVertex('E'); //4

        theGraph.addEdge(0, 1, 50);
        theGraph.addEdge(0, 3, 80);
        theGraph.addEdge(1, 2, 60);
        theGraph.addEdge(1, 3, 90);
        theGraph.addEdge(2, 4, 40);
        theGraph.addEdge(3, 2, 20);
        theGraph.addEdge(3, 4, 70);
        theGraph.addEdge(4, 1, 50);

        System.out.println("最短路径:");
        theGraph.path();
        System.out.println();
    }
}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值